import java.util.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JRadioButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;

public class GUIDBPanel extends JApplet implements ActionListener
{
	//---------------------------------------------
	// Needed to please eclipse for some reason
	//
	private static final long serialVersionUID = 1L;
	
	//--------------------------------------------
    // combined to create the output window
    //
	JTextPane output;
	JScrollPane scrollPane;
	
	//--------------------------------------------
    // db panel declarations
    //
	private JPanel dbControls;
	private JPanel buttonPanel;
	private JTextField tableNames;
	private JTextField ODBC;
	private JTextField fieldTypeNames;
	private JTextField txtFileName;
	private JComboBox delimiterBox;
	
	private JRadioButton returnDB;
	private JRadioButton insertDB;
		
	private JButton clearAll;
	private JButton submit;
	private JButton open;
	
	private JPanel optionPanel;
	
	private JPanel dbPanel;
	
	private JPanel dynamicCheckPanel;
	private GridLayout grid;
		
	private DataInputStream targetFileStream;
		
	public void init()
	{		
		this.setSize(new Dimension(600, 600));
	}
	
	public GUIDBPanel()
	{
		//-------------------------------------------
        //Create the screen
		//
        JPanel screen = new JPanel(new BorderLayout());
        scrollPane = new JScrollPane();
        output = new JTextPane();
        scrollPane.getViewport().add(output);
        
        screen.setBackground(new Color(255, 255, 255));
        screen.setSize(new Dimension(200, 200));
        
        screen.add(scrollPane, BorderLayout.CENTER);
        
        setupReturn();
        setupDBPanel();
        
        //-------------------------------------------
        // Set the menu bar and add the label to the content pane using grid bag layout manager.
        //        
        dbPanel = new JPanel(new GridBagLayout());
		dbPanel.add(screen, getConstraints(0, 0));
        dbPanel.add(dbControls, getConstraints(0, 1));
        
        //-------------------------------------------
        // Amusing introductory message goes here
        //
        printToScreen("DB Panel\n\n");
	}
	
	public JPanel getDBPanel()
	{
		return dbPanel;
	}
	
	//-------------------------------------------
    // Retrieves location grid bag constraints for panel
    //
	private GridBagConstraints getConstraints(int x, int y)
	{
		return getConstraints(x, y, 1, 1);
	}
	
	//-------------------------------------------
    // Retrieves location and size grid bag constraints for panel
    //
	private GridBagConstraints getConstraints(int x, int y, int w, int h)
	{
		GridBagConstraints constraints = new GridBagConstraints();
		
		constraints.fill       = GridBagConstraints.HORIZONTAL;
		constraints.gridx      = x;
		constraints.gridy      = y;
		constraints.gridwidth  = w;
		constraints.gridheight = h;
		
		return constraints;
	}
	
	public void printToScreen(String text)
	{
		try
		{
			output.getDocument().insertString(output.getDocument().getLength(), text, null);
			output.setCaretPosition(output.getDocument().getLength());
		}
		catch (BadLocationException e)
		{
			e.printStackTrace();
		}
	}
	
	//-------------------------------------------
    // Opens the target file and returns the contexts
	// as a DataInputStream.
    //
	private void openFile(String fileName)
	{
		if (fileName.isEmpty())
		{
			printToScreen("Please enter a filename.\n");
			return;
		}
		
		try
		{
			File f = new File(fileName);// file name  
			FileInputStream fis = new FileInputStream(f);
			BufferedInputStream bis = new BufferedInputStream(fis);
			targetFileStream = new DataInputStream(bis);
		}
		catch (FileNotFoundException e)
		{
			printToScreen("Error encountered opening target file.\n");
			targetFileStream = null;
		}
	}
	
	//-------------------------------------------
    // Creates the database panel
    //
	private void setupDBPanel()
	{
		dbControls = new JPanel();
		buttonPanel = new JPanel();
		
		dbControls.setLayout(new GridBagLayout());
		
		//-------------------------------------------
	    // Creates panel titled "Select return parameters"
		// and assign it to grid position y = 0
	    //
		dbControls.add(optionPanel, getConstraints(0, 0));
		
		//-------------------------------------------
	    // Creates panel titled "File Name"
		// and assign it to grid position y = 2
	    //
		JPanel txtFileNamePanel = new JPanel();
		txtFileNamePanel.setBorder(BorderFactory.createTitledBorder("File Name"));
		txtFileName = new JTextField(20);
		txtFileNamePanel.add(txtFileName);
		dbControls.add(txtFileNamePanel, getConstraints(0, 1));
		
		//-------------------------------------------
	    // Creates panel titled "ODBC Name"
		// and assign it to grid position y = 3
	    //
		JPanel ODBCPanel = new JPanel();
		ODBCPanel.setBorder(BorderFactory.createTitledBorder("ODBC Name"));
		ODBC = new JTextField(20);							// Mark's comment: note that we still need to ask for the
		ODBCPanel.add(ODBC);								// user to tell us where they set up the db file at.
		dbControls.add(ODBCPanel, getConstraints(0, 2));
		
		//-------------------------------------------
	    // Creates panel titled "Table Names"
		// and assign it to grid position y = 4
	    //
		JPanel tableNamePanel = new JPanel();
		tableNamePanel.setBorder(BorderFactory.createTitledBorder("Table Names"));
		tableNames = new JTextField(20);
		tableNamePanel.add(tableNames);
		dbControls.add(tableNamePanel, getConstraints(0, 3));
		
		//-------------------------------------------
	    // Creates panel titled "Field Names and Types" with instructions
		// and assign it to grid position y = 5
	    //
		JPanel instPanel = new JPanel();
		JLabel instLabel = new JLabel("<html><p align=center>Field Name and type format should appear as <br>i.e. cars VARCHAR, year INT</p><html>");
		instPanel.add(instLabel);
		open = new JButton("Select subset");
		open.addActionListener(this);
		fieldTypeNames = new JTextField(20);
		JPanel fieldPanel = new JPanel();
		fieldPanel.setLayout(new GridBagLayout());
		fieldPanel.setBorder(BorderFactory.createTitledBorder("Field Names and Types"));
		fieldPanel.add(fieldTypeNames, getConstraints(0, 0));
		fieldPanel.add(open, getConstraints(1, 0));
		fieldPanel.add(instPanel, getConstraints(0, 1, 2, 1));
		dbControls.add(fieldPanel, getConstraints(0, 4));
		
		//-------------------------------------------
	    // Creates dynamic panel titled "Select Subset of Entries"
		// 
	    //
		dynamicCheckPanel = new JPanel();
		dynamicCheckPanel.setBorder(BorderFactory.createTitledBorder("Select Subset of Entries"));
		grid = new GridLayout(1,3);
		dynamicCheckPanel.setLayout(grid);
		
		//-------------------------------------------
	    // Creates panel titled "ODBC Name"
		// and assign it to grid position x = 6
	    //		
		dbControls.add(dynamicCheckPanel, getConstraints(0, 5));
		dynamicCheckPanel.setVisible(false);
		
		//-------------------------------------------
	    // Creates drop-down panel titled "Delimiter Type"
		// and assign it to grid position y = 7
	    //
		JPanel delimiterPanel = new JPanel();
		delimiterPanel.setBorder(BorderFactory.createTitledBorder("Delimiter Type"));
		String[] delimiterStrings = { "White Space", "Comma"};
		delimiterBox = new JComboBox(delimiterStrings);
		delimiterBox.setSelectedIndex(0);
		delimiterBox.addActionListener(this);
		delimiterPanel.add(delimiterBox);
		dbControls.add(delimiterPanel, getConstraints(0, 6));
		
		//-------------------------------------------
	    // Creates panel for placing the "SEND" and "CLEAR ALL" button
		// and assign it to grid position y = 8
	    //
		submit = new JButton("SEND");
		submit.addActionListener(this);
		buttonPanel.add(submit);
		clearAll = new JButton("CLEAR ALL");
		clearAll.addActionListener(this);
		buttonPanel.add(clearAll);
		dbControls.add(buttonPanel, getConstraints(0, 7));
	}
	
	//-------------------------------------------
    // Creates the return type selection menu
    //
	private void setupReturn()
	{
		
		optionPanel = new JPanel();
		optionPanel.setBorder(BorderFactory.createTitledBorder("Select return parameters"));
		
		returnDB = new JRadioButton("Create Data Base");
		ButtonGroup group = new ButtonGroup();
		insertDB = new JRadioButton("Insert Data");
		group.add(returnDB);
		group.add(insertDB);
				
		optionPanel.add(returnDB);
		optionPanel.add(insertDB);
		
	}
	
	//String tokenizer function
	//use to parse the type and field line
	public String[] parseString(String line)
	{
		StringTokenizer tokenizer;
		
		//Mark's comment: I'm sure there is a better way to do this
		String val[] = new String[line.length()];
		int i = 0;
		
		tokenizer = new StringTokenizer(line, ",");
		while(tokenizer.hasMoreTokens())
		{
			val[i] = tokenizer.nextToken();
			i++;
		}
		
		return val;
	}
	/* Need to handle the actions performed by each entry from
	 * user.
	 */
	public void actionPerformed(ActionEvent action) 
	{
		RunDB runDB = new RunDB();
		String fTypeName[] = null; //will store the name and type for field
		String tNames = null;
		
		ArrayList<String> subsetFieldNames = new ArrayList<String>();//will store the subset of fields selected by user.
		
		//Mark's Comment: default the delimiter to whitespace unless otherwise
		//told to do so.
		String delim = " ";
		
		//Mark's Comment: handle the textbox selection for delimiter
		//this will be used for parse group to parse 
		//text file
		if (delimiterBox.getSelectedIndex() == 0)
		{
			delim = " ";
		}
		else
		{
			delim = ",";
		}
		
		// try-catch block for handling button actions
		try
		{
			// case: user clicks the "SEND" button
			if (action.getSource() == submit)
			{				
				//populating the subset of fields selected by user
				Component component[] = dynamicCheckPanel.getComponents();
				for(int i = 0; i < component.length; i++)
				{
					if (component[i] instanceof JCheckBox) 
					{
						JCheckBox checkBox = (JCheckBox) component[i];
						if(checkBox.isSelected())
						{
							subsetFieldNames.add(checkBox.getText());
						}
					}
				}
				
				
				//-----------------------------
				// Open the target file for reading and dump contents into targetFileStream
				//
				openFile(txtFileName.getText());
				if (null != targetFileStream)
				{
					printToScreen("File opened\n");
				}
				else
				{
					return;
				}
				
				//Mark's Comment: only bother to do if we want to actually create
				//the database
				if (returnDB.isSelected())
				{
					//make sure we have some sort of entry
					if (!tableNames.getText().equals(""))
					{
						
						//Mark's Comment: the user is only allowed one table entry
						tNames = tableNames.getText();
					}
														
					runDB.loadDriver();
					runDB.makeConnection(ODBC.getText());
					runDB.buildStatement();
		        
					//Mark's comment: this is the function that creates the DB
					runDB.createDB(this,tNames,subsetFieldNames);
					printToScreen("DB Create complete\n");
				}
				
				/*Mark's Comment: this will allow insertion of new data into the newly created
				 * database.
				 */
				if (insertDB.isSelected())
				{
					//mark's comment: allows the user to create DB first, then
					//that way this will be pulled again.
					if (!fieldTypeNames.getText().equals(""))
					{
						fTypeName = parseString(fieldTypeNames.getText());
					}
					tNames = tableNames.getText();
					
					PopulateDB populateDB = new PopulateDB();
					populateDB.initialize(tNames, fTypeName, subsetFieldNames, txtFileName.getText(), delim,
							ODBC.getText());
					printToScreen("Data inserted into DB\n");
				}
			}
			
			// case: user clicks the "CLEAR ALL" button
			if (action.getSource() == clearAll)
			{
				//clear the screen
				output.setText("");
				
				//reset the check boxes
				dynamicCheckPanel.setVisible(false);
				dynamicCheckPanel.removeAll();
				dynamicCheckPanel.revalidate();
			}
			
			// case: user clicks the "Select subset" button
			// NOTES:
			// * sample form of input is: [(field name) (type)]*
			//     (e.g., cars VARCHAR, year INT)
			// * add error checking if user enters retarded stuff
			if (action.getSource() == open)
			{
				//reset the check boxes
				dynamicCheckPanel.setVisible(false);
				dynamicCheckPanel.removeAll();
				dynamicCheckPanel.revalidate();
				
				// create a list to store the dynamically-created check boxes
				LinkedList<JCheckBox> dynamicLinkedList = new LinkedList<JCheckBox>();
				
				StringTokenizer tokenizer;
				
				// tokenize the field with the comma (,) set as the token
				tokenizer = new StringTokenizer(fieldTypeNames.getText(), ",");
				
				// loop through each token of form [(field name) (type)]
				while(tokenizer.hasMoreTokens())
				{
					// generate check box when there are new tokens
					JCheckBox temp = new JCheckBox(tokenizer.nextToken());
					
					temp.setSelected(true);
					
					// add check box to list of check boxes
					dynamicLinkedList.add(temp);
				}
				
				grid.setRows(dynamicLinkedList.size()/3 + 1);
				
				for (int i = 0; i < dynamicLinkedList.size(); i++)
				{
					dynamicCheckPanel.add(dynamicLinkedList.get(i));
				}
				
				dynamicCheckPanel.setVisible(true);
				dynamicCheckPanel.revalidate();
			}

		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
	}
	
}